package com.bruce.asurada.sso.util;

import com.bruce.asurada.common.Result;
import com.bruce.asurada.sso.exception.ServiceCallException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.function.Supplier;

/**
 * 服务调用工具类
 * @author Bruce
 */
@Slf4j
@Component
public class ServiceCallUtil {

    /**
     * 执行服务调用，带重试机制
     * @param serviceName 服务名称
     * @param methodName 方法名称
     * @param supplier 服务调用函数
     * @param maxRetries 最大重试次数
     * @return 调用结果
     */
    public <T> Result<T> executeWithRetry(String serviceName, String methodName, 
                                         Supplier<Result<T>> supplier, int maxRetries) {
        int attempts = 0;
        Exception lastException = null;
        
        while (attempts <= maxRetries) {
            try {
                log.debug("执行服务调用: 服务={}, 方法={}, 尝试次数={}", serviceName, methodName, attempts + 1);
                Result<T> result = supplier.get();
                
                if (result != null) {
                    log.debug("服务调用成功: 服务={}, 方法={}", serviceName, methodName);
                    return result;
                }
                
                log.warn("服务调用返回空结果: 服务={}, 方法={}", serviceName, methodName);
                throw new ServiceCallException(serviceName, methodName, "服务返回空结果", null);
                
            } catch (Exception e) {
                lastException = e;
                attempts++;
                
                if (attempts <= maxRetries) {
                    log.warn("服务调用失败，准备重试: 服务={}, 方法={}, 尝试次数={}, 错误={}", 
                            serviceName, methodName, attempts, e.getMessage());
                    
                    // 等待一段时间后重试
                    try {
                        Thread.sleep(1000 * attempts); // 递增等待时间
                    } catch (InterruptedException ie) {
                        Thread.currentThread().interrupt();
                        throw new ServiceCallException(serviceName, methodName, "重试被中断", ie);
                    }
                } else {
                    log.error("服务调用最终失败: 服务={}, 方法={}, 总尝试次数={}, 错误={}", 
                             serviceName, methodName, attempts, e.getMessage());
                }
            }
        }
        
        // 所有重试都失败了
        if (lastException instanceof ServiceCallException) {
            throw (ServiceCallException) lastException;
        } else {
            throw new ServiceCallException(serviceName, methodName, "服务调用失败", lastException);
        }
    }

    /**
     * 执行服务调用，不重试
     * @param serviceName 服务名称
     * @param methodName 方法名称
     * @param supplier 服务调用函数
     * @return 调用结果
     */
    public <T> Result<T> execute(String serviceName, String methodName, Supplier<Result<T>> supplier) {
        return executeWithRetry(serviceName, methodName, supplier, 0);
    }
}